// Configuration configuration = new Configuration(null); // getConfigurationByFilter(configuration);
streamOfOptional();
showIdentitySensitiveOperations(); }
/** * Rule #1 Never, ever, use null for an Optional variable or return value * This is safe, but hardly any better than checking for null * * @param customerList: customer * @return customer */ publicstatic Customer customerNameByID(List<Customer> customerList){ int customerID = 1; Optional<Customer> opt = customerList.stream() .filter(c -> c.getId() == customerID) .findFirst(); // here same as returning null return opt.get(); }
/** * Rule #2 Never use Optional.get() unless you can prove that the Optional is present * This is safe, but hardly any better than checking for null * * @param customerList: customer * @param customerID: customer's identity * @return customer's name */ publicstatic String customerNameByID(List<Customer> customerList, int customerID){ Optional<Customer> opt = customerList.stream() .filter(c -> c.getId() == customerID) .findFirst(); return opt.isPresent() ? opt.get().getName() : "UNKNOWN"; }
/* * Rule #3 Prefer alternatives to Optional.isPresent() and Optional.get() */
/** * continued Rule #3 Prefer alternatives to Optional.isPresent() and Optional.get() */ publicstatic String customerNameByMap(){ Customer customer = null;
// assume data happens to be null in the executing context Optional<Customer> opt = Optional.ofNullable(customer);
// orElse() can be chained directly off the result of the map() call to extract the value if present, // or the default return opt.map(Customer::getName).orElse("UNKNOWN"); }
// continued Rule #3: filter publicstaticvoidgetConfigurationByFilter(Configuration configuration){
// bad // Optional<Configuration> oparent = configuration.parent(); // if (!oparent.isPresent() || oparent.get() != configuration) { // throw new IllegalArgumentException(); // }
// continued Rule #3: streamOfOptional publicstaticvoidstreamOfOptional(){ // list of customer's id -> list of customers List<Integer> customersIDList = Stream.of(1, 2, 3).collect(Collectors.toList()); List<Customer> list = customersIDList.stream() .map(Customer::findByID) .filter(Optional::isPresent) .map(Optional::get) .collect(Collectors.toList()); System.out.println(list); }
/** * continued Rule #3: adapting between null and optional * Sometimes you need to adapt Optional-using code to code that wants null, or vice-versa */ publicstaticvoidoptionalNull(){ // If you have a nullable reference and you need an Optional // Optional<T> opt = Optional.ofNullable(null); }
/** * Rule #4: It is generally a bad idea to create an Optional for the specific purpose of chaining methods * from it to get a value * * @param s: any * @return : string */ public String process(String s){ // bad: Method Chaining is Cool, but ... // return Optional.ofNullable(s).orElse("DEFAULT");
// good: return (s != null) ? s : "DEFAULT"; }
/** * Rule #5: if an optional chain is nested or has an intermediate result of Optional, it is * probably too complex. * <p> * shortest, cleverest? the most important thing is clearest? */ publicvoidshowNestedOptional(){ Optional<BigDecimal> first = Optional.of(new BigDecimal(1)); Optional<BigDecimal> second = Optional.of(new BigDecimal(2));
Optional<BigDecimal> result;
// bad result = first.map(b -> second.map(b::add).orElse(BigDecimal.ZERO));
// good result = Optional.of(first.orElse(BigDecimal.ZERO).add(second.orElse(BigDecimal.ZERO)));
System.out.println(result); }
/** * Rule #6: avoid in fields, method parameters and collections */ publicvoidmyMethod(Optional<Object> anything){ // pass }